package com.demo.deal_service.util;

import com.demo.deal_service.enums.ImageCutEnum;
import net.coobird.thumbnailator.Thumbnails;

import java.io.*;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import static com.demo.deal_service.constant.SeparatorConstant.*;
import static com.demo.deal_service.constant.ImageConstant.*;

public class ImgUtil {

    //fixme 传入根目录可能好一些，
    public static void storeToLocal(Long dealId, InputStream imageInputStream, String module) throws IOException {
        //mkdir
        String baseDir = generateSaveDir(dealId, true);

        //将传入的imgStream拷贝两份
        InputStream[] srcInputStreams = IOUtil.copyInputStream(imageInputStream, 2);

        //save src to path pattern of "{basedir}/{id}_{timestamp}.jpg"
        String srcFileAbsolutePath = new StringBuilder()
                .append(baseDir)
                .append(FILE_SEPARATOR)
                .append(dealId)
                .append(NAME_SEPARATOR)
                .append(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")))//获取当前时间戳
                .append(SUFFIX_JPG)
                .toString();

        //将原图写入本地文件，消费第一个输入流
        FileUtil.writeFileByInputStream(new File(srcFileAbsolutePath), srcInputStreams[0]); //可能抛出io异常

        //mkdir for gen
        String baseDirGen = generateSaveDir(dealId, false);//产生裁剪图片的目录绝对地址

        //loop (cut gen save gen)
        List<ImageCutEnum> imageCutEnums = ImageCutEnum.getImageCutEnumsByModule(module);

        //消费第二份的srcInputStream，根据裁减尺寸数量拷贝输入流
        InputStream[] srcInputs = IOUtil.copyInputStream(srcInputStreams[1], imageCutEnums.size());
        LinkedList<InputStream> srcInputsLinkedList = new LinkedList<>(Arrays.asList(srcInputs));

        for (ImageCutEnum imageCutEnum : imageCutEnums) {
            String genFileAbsolutePath = new StringBuilder()
                    .append(baseDirGen) //根目录
                    .append(FILE_SEPARATOR)
                    .append(dealId) //id
                    .append(NAME_SEPARATOR)
                    .append(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")))//获取当前时间戳
                    .append(NAME_SEPARATOR)
                    .append(imageCutEnum.getSuffix()) //尺寸后缀
                    .append(SUFFIX_JPG) //jpg格式
                    .toString();
            FileOutputStream fileOutputStream = new FileOutputStream(new File(genFileAbsolutePath));
            //裁减图片，每次消费一个输入流
            cutImgStream(imageCutEnum, srcInputsLinkedList.pop(), fileOutputStream);
        }
    }

    /**
     * 将图片裁减成指定大小，格式固定为jpg
     *
     * @param imageCutEnum 裁减枚举
     * @param in           输入流
     * @param out          输出流
     * @throws IOException
     */
    public static void cutImgStream(ImageCutEnum imageCutEnum, InputStream in, OutputStream out) throws IOException {
        Thumbnails
                .of(new BufferedInputStream(in))
                .height(imageCutEnum.getHeight())
                .width(imageCutEnum.getWidth())
                .outputFormat("jpg")
                .toOutputStream(out);
    }

    /**
     * 根据商品id获取源图路径
     *
     * @param dealId
     * @return
     */
    public static String getSourceImgPath(Long dealId) {
        String baseDir = new StringBuilder()
                .append(ROOT_PATH)
                .append(FILE_SEPARATOR)
                .append(SRC_PATH)
                .append(FILE_SEPARATOR)
                .append(dealId / 1000000)
                .append(FILE_SEPARATOR)
                .append(dealId / 1000)
                .append(FILE_SEPARATOR)
                .append(LocalDateTime.now().getYear())
                .append(NAME_SEPARATOR)
                .append(LocalDateTime.now().getMonthValue())
                .toString();

        File file = new File(baseDir);
        if (!file.exists() || !file.isDirectory()) {
            return "";
        }

        //筛除无效的数据和不带有dealId的数据
        File[] validFiles = file.listFiles((File dir, String name) -> !name.contains("_INVALID") && name.split("_")[0].equals("" + dealId));

        //若存在有效文件返回文件名字最大的哪一个文件的路径
        if (validFiles == null || validFiles.length == 0) {
            return "";
        } else {
            return Arrays.stream(validFiles)
                    .max(Comparator.comparing(File::getName))
                    .orElse(new File(""))
                    .getAbsolutePath();
        }
    }

    /**
     * 根据商品id和图片裁剪枚举，获取生成图片的路径
     *
     * @param dealId
     * @param imageCutEnum
     * @return
     */
    public static String getGenImgPath(Long dealId, ImageCutEnum imageCutEnum) {
        String baseDir = new StringBuilder()
                .append(ROOT_PATH)
                .append(FILE_SEPARATOR)
                .append(GEN_PATH)
                .append(FILE_SEPARATOR)
                .append(dealId / 1000000)
                .append(FILE_SEPARATOR)
                .append(dealId / 1000)
                .append(FILE_SEPARATOR)
                .append(LocalDateTime.now().getYear())
                .append(NAME_SEPARATOR)
                .append(LocalDateTime.now().getMonthValue())
                .toString();

        File file = new File(baseDir);
        //筛除无效的数据和不带有dealId的数据
        File[] validFiles = file.listFiles((File dir, String name) -> {
            if (name.contains("_INVALID") || !name.split("_")[0].equals("" + dealId)) {
                return false;
            }

            return true;
        });

        //若存在有效文件返回文件名字最大的哪一个文件的路径
        if (validFiles == null || validFiles.length == 0) {
            return "";
        } else {
            return Arrays.stream(validFiles)
                    .filter(file1 -> file1.getName().contains(imageCutEnum.getSuffix()))
                    .max(Comparator.comparing(File::getName))
                    .orElse(new File(""))
                    .getAbsolutePath();
        }
    }

    /**
     * @param dealId
     * @param isSrc
     * @return 文件目录的绝对路径
     */
    private static String generateSaveDir(Long dealId, boolean isSrc) throws IOException {
        String baseDir = new StringBuilder()
                .append(ROOT_PATH)
                .append(FILE_SEPARATOR)
                .append(isSrc ? SRC_PATH : GEN_PATH)
                .append(FILE_SEPARATOR)//是否源文件的存放目录
                .append(dealId / 1000000)
                .append(FILE_SEPARATOR)
                .append(dealId / 1000)
                .append(FILE_SEPARATOR)
                .append(LocalDateTime.now().getYear())
                .append(NAME_SEPARATOR)
                .append(LocalDateTime.now().getMonthValue())
                .toString();

        File file = new File(baseDir);

        if (!file.exists()) {
            if (!file.mkdirs()) {
                throw new IOException("创建文件失败，io异常");
            }
        }

        return baseDir;
    }

    public static String getRelativeGenPath(Long dealId, ImageCutEnum imageCutEnum) {
        String fullFileName = null;
        File file = new File(getGenImgPath(dealId, imageCutEnum));
        if(file.exists()){
            fullFileName = file.getName();
        } else {
            return null;
        }

        return "/imggen/" + "0/" + "0/" + "2018_4/" + fullFileName;
    }

    public static String getRelativeSrcPath(Long dealId) {
        String fullFileName = null;
        File file = new File(getSourceImgPath(dealId));
        if(file.exists()){
            fullFileName = file.getName();
        } else {
            return null;
        }
        return "/imgsrc/" + "0/" + "0/" + "2018_4/" + fullFileName;
    }
}
